#include "stm8s.h"
#include "qumi_config.h"
#include "string.h"
#include "se8r01.h"
#include "misc.h"


uint8_t const TX_ADDRESS[TX_ADR_WIDTH]  = {0x34,0x43,0x10,0x10,0x01}; // Define a static TX address
unsigned char bank0_reg[][2]={
    {0,0x7F},   // Interrupt not reflected on the IRQ pin; Enable CRC; 2Byte; Poweron; PRX
    {1,0x00},   // disenable auto ackknowledgement data
    {2,0x01},   // enable pipe0
    {3,0x02},   // 4Byte Address
    {4,0x00},   // disable data Retransmission
    {5,0x17},   // Frequency channel
    {6,0x4F},   // 1Mbps; 0dBm; LNA
    {28,0x01},  // pipe0 pipe1 enable dynamic payload length data
    {29,0x07}   // enable dynamic paload lenght; enbale payload with ack enable w_tx_payload_noack
};

uint8_t gtemp[5];
uint8_t rx_buf[TX_PLOAD_WIDTH];
uint8_t tx_buf[TX_PLOAD_WIDTH];



/**************************************************
Function: init_io();
Description:
  flash led one time,chip enable(ready to TX or RX Mode),
  Spi disable,Spi clock line init high
**************************************************/
void init_se8r01_io(void)
{
	/*CSN=1;			// Spi disable	*/
	/*SCK=0;			// Spi clock line init high*/

  GPIO_WriteHigh(SPI_CS_PORT, SPI_CS_PIN);
  GPIO_WriteLow(SPI_SCK_PORT, SPI_SCK_PIN);
}
/**************************************************
Function: SPI_RW();

Description:
  Writes one byte to se8r01, and return the byte read
  from se8r01 during write, according to SPI protocol
**************************************************/
uint8_t SPI_RW(uint8_t byte)
{
	//uint8_t bit_ctr;
  uint8_t i;
  uint8_t recv = 0;

  for (i=0; i<8; i++)
  {
    if (byte&0x80) 
    {
      //High
      GPIO_WriteHigh(SPI_MOSI_PORT, SPI_MOSI_PIN);
    }
    else
    {
      //Low
      GPIO_WriteLow(SPI_MOSI_PORT, SPI_MOSI_PIN);
    }
    GPIO_WriteHigh(SPI_SCK_PORT, SPI_SCK_PIN);
    if (GPIO_ReadInputPin(SPI_MISO_PORT, SPI_MISO_PIN) != RESET)
    {
      recv |= 1;
    }
    GPIO_WriteLow(SPI_SCK_PORT, SPI_SCK_PIN);

    recv <<= 1;
    byte <<= 1;
  }
    return recv; 
}
/**************************************************/

/**************************************************
Function: SPI_RW_Reg();

Description:
  Writes value 'value' to register 'reg'
**************************************************/
uint8_t SPI_RW_Reg(uint8_t reg, uint8_t value)
{
	uint8_t status;

  GPIO_WriteLow(SPI_CS_PORT, SPI_CS_PIN);
  status = SPI_RW(reg);      // select register
  SPI_RW(value);             // ..and write value to it..
  GPIO_WriteHigh(SPI_CS_PORT, SPI_CS_PIN);
  return status;            // return se8r01 status byte
}

/**************************************************
Function: SPI_Read();

Description:
  Read one byte from se8r01 register, 'reg'
**************************************************/
uint8_t SPI_Read(uint8_t reg)
{
	uint8_t reg_val;

  GPIO_WriteLow(SPI_CS_PORT, SPI_CS_PIN);
  SPI_RW(reg);            // Select register to read from..
  reg_val = SPI_RW(0);    // ..then read registervalue
  GPIO_WriteHigh(SPI_CS_PORT, SPI_CS_PIN);

  return reg_val;        // return register value
}


/**************************************************
Function: SPI_Read_Buf();

Description:
  Reads 'bytes' #of bytes from register 'reg'
  Typically used to read RX payload, Rx/Tx address
**************************************************/
uint8_t SPI_Read_Buf(uint8_t reg, uint8_t *pBuf, uint8_t bytes)
{
	uint8_t status   = 0;
  uint8_t byte_ctr = 0;

  if ((pBuf == 0) || (bytes == 0))
  {
    return 0;
  }

  GPIO_WriteLow(SPI_CS_PORT, SPI_CS_PIN);
  status = SPI_RW(reg);       		// Select register to write to and read status byte

  for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)
  {
    pBuf[byte_ctr] = SPI_RW(0);    // Perform SPI_RW to read byte from se8r01
  }

  GPIO_WriteHigh(SPI_CS_PORT, SPI_CS_PIN);

  return status;                    // return se8r01 status byte
}

/**************************************************
Function: SPI_Write_Buf();

Description:
  Writes contents of buffer '*pBuf' to se8r01
  Typically used to write TX payload, Rx/Tx address
**************************************************/
uint8_t SPI_Write_Buf(uint8_t reg, uint8_t *pBuf, uint8_t bytes)
{
	uint8_t status,byte_ctr;

  if ((pBuf == 0) || (bytes == 0))
  {
    return 0;
  }

  GPIO_WriteLow(SPI_CS_PORT, SPI_CS_PIN);

  status = SPI_RW(reg);    // Select register to write to and read status byte

  for(byte_ctr=0; byte_ctr<bytes; byte_ctr++) // then write all byte in buffer(*pBuf)
  {
    SPI_RW(*pBuf++);
  }

  GPIO_WriteHigh(SPI_CS_PORT, SPI_CS_PIN);

  return  status;          // return se8r01 status byte
}

/**************************************************
Function: RX_Mode();

Description:
  This function initializes one se8r01 device to
  RX Mode, set RX address, writes RX payload width,
  select RF channel, datarate & LNA HCURR.
  After init, CE is toggled high, which means that
  this device is now ready to receive a datapacket.
**************************************************/
void power_off()
{
  //TODO: TEST CE
  /*CE=0;*/
  SPI_RW_Reg(WRITE_REG + CONFIG, 0x0D); 
  /*CE=1;*/
  DelayUS(20);
}

void ifnnrf_rx_mode(void)
{
  power_off();
	/*CE=0;*/
  SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // Use the same address on the RX device as the TX device
  SPI_RW_Reg(iRF_CMD_WRITE_REG|iRF_BANK0_STATUS,0x70);

  SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);      // Enable Auto.Ack:Pipe0
  SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  // Enable Pipe0
  SPI_RW_Reg(WRITE_REG + RF_CH, 40);        // Select RF channel 40
  SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // Select same RX payload width as TX Payload width
  SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x4f);   // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR //TODO:DataRate LOW
  SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);     // Set PWR_UP bit, enable CRC(2 bytes) & Prim:RX. RX_DR enabled..

  /*CE = 1; // Set CE pin high to enable RX device*/

//  This device is now ready to receive one packet of 16 bytes payload from a TX device sending to address
//  '3443101001', with auto acknowledgment, \retransmit count of 10, RF channel 40 and datarate = 2Mbps.

}
/**************************************************/

/**************************************************
Function: TX_Mode();

Description:
  This function initializes one se8r01 device to
  TX mode, set TX address, set RX address for auto.ack,
  fill TX payload, select RF channel, datarate & TX pwr.
  PWR_UP is set, CRC(2 bytes) is enabled, & PRIM:TX.

  ToDo: One high pulse(>10us) on CE will now send this
  packet and expext an acknowledgment from the RX device.
**************************************************/
void rf_switch_bank(unsigned char bankindex)
{
    unsigned char temp0,temp1;
    temp1 = bankindex;

    temp0 = SPI_RW(iRF_BANK0_STATUS);

    if((temp0&0x80)!=temp1)
    {
        SPI_RW_Reg(iRF_CMD_ACTIVATE,0x53);
    }
}

void ifnnrf_tx_mode(void)
{
  power_off();
  /*CE=0;*/
  SPI_RW_Reg(iRF_CMD_WRITE_REG|iRF_BANK0_STATUS,0x70);

  SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // Writes TX_Address to se8r01
  SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.Ack
  SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // Writes data to TX payload

  SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);      // Enable Auto.Ack:Pipe0
  SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  // Enable Pipe0
  SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...
  SPI_RW_Reg(WRITE_REG + RF_CH, 40);        // Select RF channel 40
  SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x4f);   // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR //TODO:DataRate low
  SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);     // Set PWR_UP bit, enable CRC(2 bytes) & Prim:TX. MAX_RT & TX_DS enabled..
  /*CE=1;*/

}

void SPI_CLR_Reg(uint8_t R_T)
{
  GPIO_WriteLow(SPI_CS_PORT, SPI_CS_PIN);

	if(R_T==1)                  // CSN low, init SPI transaction
  {
  	SPI_RW(FLUSH_TX);             // ..and write value to it..
  }
	else
  {
    SPI_RW(FLUSH_RX);             // ..and write value to it..
  }

  GPIO_WriteHigh(SPI_CS_PORT, SPI_CS_PIN);
}

void ifnnrf_CLERN_ALL()
{
  SPI_CLR_Reg(0);
  SPI_CLR_Reg(1);
  SPI_RW_Reg(WRITE_REG+STATUS,0xff);
  /*IRQ=1;*/
}

void rf_init(void)
{
  unsigned char i,j;

  /*CE=0;//mRF_CE_LOW_TX;*/
  DelayUS(50);							 

  for(j=0; j<3; j++)
  {
      rf_switch_bank(iBANK0);
      SPI_RW_Reg(iRF_CMD_WRITE_REG|iRF_BANK0_CONFIG,0x03);
      SPI_RW_Reg(iRF_CMD_WRITE_REG|iRF_BANK0_RF_CH,0x32);
      SPI_RW_Reg(iRF_CMD_WRITE_REG|iRF_BANK0_RF_SETUP,0x48);
      SPI_RW_Reg(iRF_CMD_WRITE_REG|iRF_BANK0_PRE_GURD,0x77); //2450 calibration

      rf_switch_bank(iBANK1);

      gtemp[0]=0x40;
      gtemp[1]=0x00;
      gtemp[2]=0x10;
      gtemp[3]=0xE6;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_PLL_CTL0, gtemp, 4);

      gtemp[0]=0x20;
      gtemp[1]=0x08;
      gtemp[2]=0x50;
      gtemp[3]=0x40;
      gtemp[4]=0x50;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_CAL_CTL, gtemp, 5);

      gtemp[0]=0x00;
      gtemp[1]=0x00;
      gtemp[2]=0x1E;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_IF_FREQ, gtemp, 3);

      gtemp[0]=0x29;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_FDEV, gtemp, 1);

      gtemp[0]=0x00;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_DAC_CAL_LOW, gtemp, 1);

      gtemp[0]=0x7F;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_DAC_CAL_HI, gtemp, 1);

      gtemp[0]=0x02;
      gtemp[1]=0xC1;
      gtemp[2]=0xEB;
      gtemp[3]=0x1C;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_AGC_GAIN, gtemp, 4);

      gtemp[0]=0x97;
      gtemp[1]=0x64;
      gtemp[2]=0x00;
      gtemp[3]=0x81;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_RF_IVGEN, gtemp, 4);

      rf_switch_bank(iBANK0);

      /*CE=1;//mRF_CE_HIGH_TX;*/
      /*DelayUS(30);*/
      /*CE=0;*/

      DelayMS(50);                            // delay 50ms waitting for calibaration.

      /*CE=1;//mRF_CE_HIGH_TX;*/
      /*DelayUS(30);*/
      /*CE=0;//mRF_CE_LOW_TX;*/

      /*DelayMS(50);                            // delay 50ms waitting for calibaration.*/
    // calibration end

      for(i=0;i<9;i++)
      {
          SPI_RW_Reg((iRF_CMD_WRITE_REG|bank0_reg[i][0]),bank0_reg[i][1]);
      }

      gtemp[0]=0x28;
      gtemp[1]=0x32;
      gtemp[2]=0x80;
      gtemp[3]=0x90;
      gtemp[4]=0x00;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK0_SETUP_VALUE, gtemp, 5);

      DelayMS(2);

      rf_switch_bank(iBANK1);

      gtemp[0]=0x40;
      gtemp[1]=0x01;
      gtemp[2]=0x30;
      gtemp[3]=0xE2;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_PLL_CTL0, gtemp, 4);

      gtemp[0]=0x29;
      gtemp[1]=0x89;
      gtemp[2]=0x55;
      gtemp[3]=0x40;
      gtemp[4]=0x50;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_CAL_CTL, gtemp, 5);

      gtemp[0]=0x29;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_FDEV, gtemp, 1);

      gtemp[0]=0x55;
      gtemp[1]=0xC2;
      gtemp[2]=0x09;
      gtemp[3]=0xAC;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_RX_CTRL, gtemp, 4);

      gtemp[0]=0x00;
      gtemp[1]=0x14;
      gtemp[2]=0x08;
      gtemp[3]=0x29;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_FAGC_CTRL_1, gtemp, 4);

      gtemp[0]=0x02;
      gtemp[1]=0xC1;
      gtemp[2]=0xCB;
      gtemp[3]=0x1C;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_AGC_GAIN, gtemp, 4);

      gtemp[0]=0x97;
      gtemp[1]=0x64;
      gtemp[2]=0x00;
      gtemp[3]=0x01;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_RF_IVGEN, gtemp, 4);

      gtemp[0]=0x2A;
      gtemp[1]=0x04;
      gtemp[2]=0x00;
      gtemp[3]=0x7D;
      SPI_Write_Buf(iRF_CMD_WRITE_REG|iRF_BANK1_TEST_PKDET, gtemp, 4);

      rf_switch_bank(iBANK0);

// rf testself
      //brf_status_error = 0;
      if(0x17 == SPI_RW(iRF_BANK0_RF_CH))
      {
          SPI_RW_Reg(iRF_CMD_WRITE_REG|iRF_BANK0_STATUS,0x70);

#if 0
          if(IRQ)
          {
              /*CE=1;//mRF_CE_HIGH_TX;*/
              //rf_write_fifo(1);	-------------------------------------------------------------
              DelayMS(1);
              if(IRQ==0)
              {
                  /*CE=0;//mRF_CE_LOW_TX;*/
                  SPI_RW_Reg(iRF_CMD_WRITE_REG|iRF_BANK0_STATUS,0x70);
                  return;
              }
              /*CE=0;//mRF_CE_LOW_TX;*/
              SPI_RW_Reg(iRF_CMD_WRITE_REG|iRF_BANK0_STATUS,0x70);
          }
#endif
      }
      //brf_status_error = 1;
  }
}

void Se8r01_Init(void)
{
  init_se8r01_io();
  rf_init();
  ifnnrf_tx_mode();
}

void Se8r01_Task(void)
{
  uint8_t sta;

  tx_buf[0] = 1;
  tx_buf[1] = 2;

  ifnnrf_tx_mode();
  sta = SPI_Read(STATUS);
  SPI_RW_Reg(WRITE_REG+STATUS,0xff);
  
  if (!(sta & STA_MARK_TX))
  {
    ifnnrf_CLERN_ALL();
  }
}
